package lxs.tool.liberator.work.service.imp;


import lxs.tool.liberator.common.base.result.Response;
import lxs.tool.liberator.common.utils.IDCreator;

import lxs.tool.liberator.system.config.DynamicDataSource;
import lxs.tool.liberator.work.mapper.ClassMapper;
import lxs.tool.liberator.work.mapper.ColumnMapper;
import lxs.tool.liberator.work.mapper.InterfaceMapper;
import lxs.tool.liberator.work.mapper.ProjectMapper;
import lxs.tool.liberator.work.param.in.ColumnIn;
import lxs.tool.liberator.work.param.in.MultiOptions;
import lxs.tool.liberator.work.pojo.Column;
import lxs.tool.liberator.work.pojo.Interface;
import lxs.tool.liberator.work.pojo.Project;
import lxs.tool.liberator.work.service.ColumnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.sql.SQLException;
import java.util.*;

@Service("ColumnServiceImp")
public class ColumnServiceImp implements ColumnService {
    private static final List<String> STRING = Arrays.asList("char", "varchar", "tinytext", "text", "mediumtext", "longtext");
    private static final List<String> INTEGER = Arrays.asList("tinyint", "smallint", "mediumint", "mediumint", "int", "bigint");
    @Autowired
    private ColumnMapper columnMapper;
    @Autowired
    private ClassMapper classMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private DynamicDataSource dbSourceService;
    @Autowired
    private InterfaceMapper interfaceMapper;

    @Override
    public Response showTable() {
        Project mainProject = projectMapper.getMainProject();
        return Response.send(columnMapper.showTable(mainProject.getId()));
    }

    @Override
    public Response getMeta() throws SQLException {
        Project mainProject = projectMapper.getMainProject();
        dbSourceService.switchTo(mainProject);
        Project project = projectMapper.selectById(mainProject.getId());
        List<Column> metas = columnMapper.getMeta(project.getDbname(), mainProject.getId());
        auto(metas);
        dbSourceService.switchBack();
        return Response.success();
    }

    /**
     * 将从元数据中查出来的信息自动入表
     *
     * @param metas 元数据
     */
    private void auto(List<Column> metas) {
        Map<String, List<String>> map = new HashMap<>();
        for (Column c : metas) {
            List<String> list = map.get(c.getClassId());
            if (list == null) {
                ArrayList<String> arrayList = new ArrayList<>();
                map.put(c.getClassId(), arrayList);
                list = arrayList;
            }
            list.add(c.getColumnName());
        }
        for (String id : map.keySet()) {
            columnMapper.deleteByClassIdAndUnExist(id, map.get(id));
        }
        for (Column c : metas) {
            c.setId(IDCreator.get("column"));
            c.setFiledName(nameCamel(c.getColumnName()));
            c.setFiledType(judgeType(c.getColumnType()));
            if (c.getLength() == null) {
                String type = c.getType();
                if (type.contains("(")) c.setLength(type.substring(type.indexOf("(") + 1, type.indexOf(")")));
                else c.setLength("11");
            }
            if (c.getFiledType().equals("String"))
                c.setValueRule("[0-z]{" + c.getLength() + "}");
            else {
                c.setValueRule("[0-9]{" + c.getLength() + "}");
            }
            String s = columnMapper.judgeExist(c.getClassId(), c.getColumnName());
            if (!StringUtils.hasLength(s)) columnMapper.insert(c);
            else {
                Column exist = columnMapper.getTheExist(c.getClassId(), c.getColumnName());
                exist.setComment(c.getComment());
                exist.setColumnType(c.getColumnType());
                exist.setKey(c.getKey());
                exist.setLength(c.getLength());
                exist.setFiledType(c.getFiledType());
                columnMapper.updateById(exist);
            }
        }
    }

    @Override
    public Response setRules(ColumnIn in) {
        List<ColumnIn> children = in.getChildren();
        StringBuilder s = new StringBuilder();
        //1变量[]
        //2常量<>
        //3自定句()
        //次数{}
        if (children.get(0).getKey().equals(3 + "")) {
            s.append("(");
            for (ColumnIn c : children.get(0).getChildren()) {
                s.append(c.getValue()).append("|");
            }
            s.replace(s.length() - 1, s.length(), ")");
        } else {
            for (ColumnIn c : children) {
                if (c.getKey().equals(1 + "")) {
                    s.append(c.getValue()).append("{").append(c.getTime()).append("}").append("&&");
                } else {
                    s.append("<").append(c.getValue()).append(">{").append(c.getTime()).append("}").append("&&");
                }
            }
            s.replace(0, s.length(), s.substring(0, s.length() - 2));
        }
        columnMapper.setRules(s.toString(), in.getId());
        return Response.success();
    }

    @Override
    public Response getListByClassId(String classId) {
        return Response.send(columnMapper.getListByClassId(classId));
    }

    @Override
    public Response setLink(String link, String id) {
        columnMapper.setLink(link, id);
        return Response.success();
    }

    @Override
    public Response getMultiOptions() {
        List<MultiOptions> options = classMapper.getOptions(projectMapper.getMainProject().getId());
        for (MultiOptions m : options) {
            m.setChildren(columnMapper.getOptionsByClassId(m.getKey()));
        }
        return Response.send(options);
    }

    @Override
    public Response getOptionsByClassIdAndHaveLink(String cid) {
        return Response.send(columnMapper.getOptionsByClassIdAndHaveLink(cid));
    }

    @Override
    public Response getOptionsByClassId(String id) {
        return Response.send(columnMapper.getOptionsByClassId(id));
    }

    @Override
    public Response getOptionsByInterfaceId(String iid) {
        Interface anInterface = interfaceMapper.selectById(iid);
        String classId = anInterface.getClassId();
        return Response.send(columnMapper.getOptionsByClassId(classId));
    }


    private String nameCamel(String name) {
        StringBuilder sb = new StringBuilder(name);
        if (sb.charAt(0) == '_') sb.replace(0, 1, "");
        if (sb.charAt(sb.length() - 1) == '_') sb.replace(sb.length() - 1, sb.length(), "");
        int i = sb.indexOf("_");
        if (i != -1) {
            sb.replace(i, i + 2, (sb.charAt(i + 1) + "").toUpperCase());
            return nameCamel(sb.toString());
        }
        return name;
    }

    private String judgeType(String type) {
        if (type.equals("bigint")) return "BigInteger";
        if (type.equals("decimal")) return "BigDecimal";
        if (type.equals("float")) return "Float";
        if (STRING.contains(type)) return "String";
        if (INTEGER.contains(type)) return "Integer";
        return "Double";
    }
}
